package com.makefuture.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 基础加密组件
 * <p/>
 * 
 * <pre>
 * BASE64加密解密
 * MD5单项加密
 * SHA单项加密
 * HMAC单项带秘钥加密
 * </pre>
 * 
 * @author Zhang Jia ning
 * @version 1.0
 * @date 2015-08-11
 */
public class Encryption {

	public static final String ENCODING_DEFAULT = "UTF-8";
	public static final String ENCODING_UTF8 = "UTF-8";
	public static final String ENCODING_GBK = "GBK";

	// //////////////////////////////////////////////////////////
	// BASE64加密解密
	// //////////////////////////////////////////////////////////

	/**
	 * BASE64加密
	 * 
	 * @param data
	 *            需要加密的字节数组
	 * @return 加密后的字符串
	 */
	public static String encryptBASE64(byte[] data) {
		return new BASE64Encoder().encodeBuffer(data).trim();
	}

	/**
	 * BASE64加密(采用默认编码UTF-8)
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptBASE64(String data) {
		String result = null;
		try {
			result = encryptBASE64(data.getBytes(ENCODING_DEFAULT));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * BASE64加密(采用默认编码UTF-8)
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param encoding
	 *            字符编码
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptBASE64(String data, String encoding) {
		String result = null;
		try {
			result = encryptBASE64(data.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * BASE64解密
	 * 
	 * @param data
	 *            需要解密的加密字符串
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static byte[] decryptBASE64(String data) {
		byte[] result = null;
		try {
			result = new BASE64Decoder().decodeBuffer(data);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * BASE64解密
	 * 
	 * @param data
	 *            需要解密的加密字符串
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptBASE64ToString(String data) {
		String result = null;
		try {
			result = new String(decryptBASE64(data), ENCODING_DEFAULT);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * BASE64解密
	 * 
	 * @param data
	 *            需要解密的加密字符串
	 * @param encoding
	 *            字符编码
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptBASE64ToString(String data, String encoding) {
		String result = null;
		try {
			result = new String(decryptBASE64(data), encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	// //////////////////////////////////////////////////////////
	// MD5加密
	// //////////////////////////////////////////////////////////

	/**
	 * MD5加密
	 * 
	 * @param key
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptMD5(byte[] data) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		md5.update(data);
		return md5.digest();
	}

	/**
	 * MD5加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptMD5ToString(byte[] data) {
		return bytesToHexString(encryptMD5(data));
	}

	/**
	 * MD5加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptMD5ToString(String data) {
		String result = null;
		try {
			result = encryptMD5ToString(data.getBytes(ENCODING_DEFAULT));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * MD5加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @param encoding
	 *            需要加密的数据的解析编码
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptMD5ToString(String data, String encoding) {
		String result = null;
		try {
			result = encryptMD5ToString(data.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	// //////////////////////////////////////////////////////////
	// SHA加密
	// //////////////////////////////////////////////////////////

	/**
	 * SHA加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptSHA(byte[] data) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("SHA");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		md5.update(data);
		return md5.digest();
	}

	/**
	 * SHA加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptSHAToString(byte[] data) {
		return bytesToHexString(encryptSHA(data));
	}

	/**
	 * SHA加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptSHAToString(String data) {
		String result = null;
		try {
			result = encryptSHAToString(data.getBytes(ENCODING_DEFAULT));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * SHA加密
	 * 
	 * @param data
	 *            需要加密的数据
	 * @param encoding
	 *            需要加密的数据的解析编码
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static String encryptSHAToString(String data, String encoding) {
		String result = null;
		try {
			result = encryptSHAToString(data.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	// //////////////////////////////////////////////////////////
	// HMAC带秘钥加密
	// //////////////////////////////////////////////////////////
	/**
	 * 获取秘钥，MAC算法可选以下多种算法
	 * <p/>
	 * 
	 * <pre>
	 * HmacMD5
	 * HmacSHA1
	 * HmacSHA256
	 * HmacSHA384
	 * HmacSHA512
	 * </pre>
	 */
	public static final String HMAC_KEY_MAC_MD5 = "HmacMD5";
	public static final String HMAC_KEY_MAC_SHA1 = "HmacSHA1";
	public static final String HMAC_KEY_MAC_SHA256 = "HmacSHA256";
	public static final String HMAC_KEY_MAC_SHA384 = "HmacSHA384";
	public static final String HMAC_KEY_MAC_SHA512 = "HmacSHA512";

	/**
	 * 生成HMAC秘钥
	 * 
	 * @return HMAC秘钥
	 * @throws Exception
	 */
	public static byte[] generatorHMACKey() {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(HMAC_KEY_MAC_MD5);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom();
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成HMAC秘钥
	 * 
	 * @param key
	 *            秘钥
	 * @return HMAC秘钥
	 * @throws Exception
	 */
	public static byte[] generatorHMACKey(byte[] key) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(HMAC_KEY_MAC_MD5);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom(key);
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成HMAC秘钥
	 * 
	 * @param kayMac
	 *            秘钥算法
	 * @return 秘钥字符串
	 * @throws Exception
	 */
	public static byte[] generatorHMACKey(String kayMac) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(kayMac);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom();
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成HMAC秘钥
	 * 
	 * @param key
	 *            秘钥
	 * @param kayMac
	 *            秘钥算法
	 * @return HMAC秘钥
	 * @throws Exception
	 */
	public static byte[] generatorHMACKey(byte[] key, String kayMac) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(kayMac);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom(key);
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * HMAC加密(采用默认秘钥算法HmacMD5)
	 * 
	 * @param data
	 *            需要加密的数据
	 * @param key
	 *            秘钥
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptHMAC(byte[] data, byte[] key) {
		return encryptHMAC(data, key, HMAC_KEY_MAC_MD5);
	}

	/**
	 * HMAC加密(指定秘钥算法)
	 * 
	 * @param data
	 *            需要加密的数据
	 * @param key
	 *            秘钥
	 * @param kayMac
	 *            秘钥算法
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptHMAC(byte[] data, byte[] key, String kayMac) {
		SecretKey secretKey = new SecretKeySpec(key, kayMac);
		Mac mac = null;
		try {
			mac = Mac.getInstance(secretKey.getAlgorithm());
			mac.init(secretKey);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return mac.doFinal(data);
	}

	/**
	 * HMAC加密(采用默认秘钥算法HmacMD5)
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥算法
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptHMACTostring(String data, String key) {
		String result = null;
		try {
			result = bytesToHexString(encryptHMAC(
					data.getBytes(ENCODING_DEFAULT),
					key.getBytes(ENCODING_DEFAULT)));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * HMAC加密(指定秘钥算法)
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @param keyMac
	 *            秘钥算法
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptHMACTostring(String data, String key,
			String keyMac) {
		return encryptHMACTostring(data, key, keyMac, ENCODING_DEFAULT);
	}

	/**
	 * HMAC加密(指定秘钥算法)
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @param keyMac
	 *            秘钥算法
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptHMACTostring(String data, String key,
			String keyMac, String encoding) {
		String result = null;
		try {
			result = bytesToHexString(encryptHMAC(data.getBytes(encoding),
					key.getBytes(encoding), keyMac));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	// //////////////////////////////////////////////////////////
	// DES加密解密
	// //////////////////////////////////////////////////////////
	public static final String DES_KEY_ALGORITHM = "DES"; // 算法名称

	/**
	 * 算法名称/加密模式(共有以下四种工作模式)/填充方式(共有3中填充模式)
	 * <p/>
	 * 
	 * <pre>
	 * ECB：电子密码本模式
	 * CBC：加密分组链接模式
	 * CFB：加密反馈模式
	 * OFB：输出反馈模式
	 * </pre>
	 * 
	 * <pre>
	 * NoPadding
	 * PKCS5Padding
	 * ISO10126Padding
	 * </pre>
	 */
	// public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
	public static final String DES_CIPHER_ALGORITHM = "DES";

	/**
	 * 生成DES秘钥
	 * 
	 * @return DES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorDESKey() {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(DES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom();
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成DES秘钥
	 * 
	 * @param key
	 *            秘钥
	 * @return DES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorDESKey(byte[] key) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(DES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom(key);
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 根据给定秘钥生成DES加密密钥对象key
	 * 
	 * @param KeyStr
	 *            密钥字符串
	 * @return 密钥对象
	 * @throws Exception
	 */
	private static SecretKey convertToKey(byte[] key) {
		DESKeySpec desKey = null;
		SecretKeyFactory keyFactory = null;
		SecretKey securekey = null;
		try {
			desKey = new DESKeySpec(key);
			keyFactory = SecretKeyFactory.getInstance(DES_KEY_ALGORITHM);
			securekey = keyFactory.generateSecret(desKey);
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return securekey;
	}

	/**
	 * DES加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptDES(byte[] data, byte[] key) {
		byte[] result = null;

		Key deskey = convertToKey(key);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(DES_CIPHER_ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, deskey, new SecureRandom());
			result = cipher.doFinal(data);
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * DES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptDESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			result = bytesToHexString(encryptDES(data.getBytes(encoding),
					hexStringToBytes(key)));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * DES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptDESToString(String data, String key) {
		return encryptDESToString(data, key, ENCODING_DEFAULT);
	}

	/**
	 * DES解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥
	 * @return 解密后的数据
	 */
	public static byte[] decryptDES(byte[] data, byte[] key) {
		byte[] result = null;
		Key deskey = convertToKey(key);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(DES_CIPHER_ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, deskey);
			result = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * DES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptDESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			result = new String(decryptDES(hexStringToBytes(data),
					hexStringToBytes(key)), encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * DES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptDESToString(String data, String key) {
		return decryptDESToString(data, key, ENCODING_DEFAULT);
	}

	// //////////////////////////////////////////////////////////
	// 3DES加密解密
	// //////////////////////////////////////////////////////////
	private static final String TDES_KEY_ALGORITHM = "DESede";

	/**
	 * 算法名称/加密模式(共有以下四种工作模式)/填充方式(共有3中填充模式)
	 * <p/>
	 * 
	 * <pre>
	 * ECB：电子密码本模式
	 * CBC：加密分组链接模式
	 * CFB：加密反馈模式
	 * OFB：输出反馈模式
	 * </pre>
	 * 
	 * <pre>
	 * NoPadding
	 * PKCS5Padding
	 * ISO10126Padding
	 * </pre>
	 */
	// public static final String TDES_CIPHER_ALGORITHM =
	// "DESede/CBC/NoPadding";
	public static final String TDES_CIPHER_ALGORITHM = "DESede";

	/**
	 * 生成TDES秘钥
	 * 
	 * @return TDES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorTDESKey() {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(TDES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom();
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成TDES秘钥
	 * 
	 * @param key
	 *            秘钥
	 * @return TDES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorTDESKey(byte[] key) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(TDES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom(key);
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * TDES加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptTDES(byte[] data, byte[] key) {
		byte[] result = null;
		SecretKey deskey = new SecretKeySpec(key, TDES_KEY_ALGORITHM);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(TDES_CIPHER_ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, deskey);
			return cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * TDES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptTDESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			return bytesToHexString(encryptTDES(data.getBytes(encoding),
					hexStringToBytes(key)));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * TDES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptTDESToString(String data, String key) {
		return encryptTDESToString(data, key, ENCODING_DEFAULT);
	}

	/**
	 * TDES解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥
	 * @return 解密后的数据
	 * @throws Exception
	 */
	public static byte[] decryptTDES(byte[] data, byte[] key) {
		byte[] result = null;
		Key deskey = new SecretKeySpec(key, TDES_KEY_ALGORITHM);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(TDES_CIPHER_ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, deskey);
			result = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * TDES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptTDESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			result = new String(decryptTDES(hexStringToBytes(data),
					hexStringToBytes(key)), encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * TDES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptTDESToString(String data, String key) {
		return decryptTDESToString(data, key, ENCODING_DEFAULT);
	}

	// //////////////////////////////////////////////////////////
	// AES带秘钥加密解密
	// //////////////////////////////////////////////////////////
	private static final String AES_KEY_ALGORITHM = "AES"; // 秘钥加密算法

	/**
	 * 算法名称/加密模式(共有以下四种工作模式)/填充方式(共有3中填充模式)
	 * <p/>
	 * 
	 * <pre>
	 * ECB：电子密码本模式
	 * CBC：加密分组链接模式
	 * CFB：加密反馈模式
	 * OFB：输出反馈模式
	 * </pre>
	 * 
	 * <pre>
	 * NoPadding
	 * PKCS5Padding
	 * ISO10126Padding
	 * </pre>
	 */
	// public static final String AES_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
	static final String AES_CIPHER_ALGORITHM = "AES";

	/**
	 * 生成AES秘钥
	 * 
	 * @return AES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorAESKey() {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(AES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom();
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * 生成AES秘钥
	 * 
	 * @param key
	 *            秘钥
	 * @return AES秘钥
	 * @throws Exception
	 */
	public static byte[] generatorAESKey(byte[] key) {
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(AES_KEY_ALGORITHM);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SecureRandom secureRandom = new SecureRandom(key);
		kg.init(secureRandom);
		SecretKey secretKey = kg.generateKey();
		return secretKey.getEncoded();
	}

	/**
	 * AES加密
	 * 
	 * @param data
	 *            待加密数据
	 * @param key
	 *            密钥
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, byte[] key) {
		byte[] result = null;
		SecretKey secretkey = new SecretKeySpec(key, AES_KEY_ALGORITHM);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, secretkey);
			result = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * AES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptAESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			return bytesToHexString(encrypt(data.getBytes(encoding),
					hexStringToBytes(key)));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * AES加密
	 * 
	 * @param data
	 *            需要加密的字符串
	 * @param key
	 *            秘钥
	 * @return 加密后的十六进制字符串
	 * @throws Exception
	 */
	public static String encryptAESToString(String data, String key) {
		return encryptAESToString(data, key, ENCODING_DEFAULT);
	}

	/**
	 * AES解密
	 * 
	 * @param data
	 *            待解密数据
	 * @param key
	 *            密钥
	 * @return 解密后的数据
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, byte[] key) {
		byte[] result = null;
		SecretKey secretkey = new SecretKeySpec(key, AES_KEY_ALGORITHM);
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, secretkey);
			result = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * AES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @param encoding
	 *            需要加密的数据和秘钥的解析编码
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptAESToString(String data, String key,
			String encoding) {
		String result = null;
		try {
			result = new String(decrypt(hexStringToBytes(data),
					hexStringToBytes(key)), encoding);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * AES解密
	 * 
	 * @param data
	 *            需要解密的十六进制字符串
	 * @param key
	 *            秘钥
	 * @return 解密后的原始字符串
	 * @throws Exception
	 */
	public static String decryptAESToString(String data, String key) {
		return decryptAESToString(data, key, ENCODING_DEFAULT);
	}

	// //////////////////////////////////////////////////////////
	// 十六进制转换
	// //////////////////////////////////////////////////////////
	private final static byte[] HEX_BYTES = "0123456789ABCDEF".getBytes();

	/**
	 * 将byte[]转换为十六进制进制字符串
	 * 
	 * @param bytes
	 *            byte数组
	 * @return 十六进制进制字符串
	 */
	public static String bytesToHexString(byte[] bytes) {
		int l = bytes.length;
		byte[] buff = new byte[2 * l];
		for (int i = 0; i < l; i++) {
			buff[2 * i] = HEX_BYTES[(bytes[i] >> 4) & 0x0f];
			buff[2 * i + 1] = HEX_BYTES[bytes[i] & 0x0f];
		}
		return new String(buff);
	}

	/**
	 * 将十六进制进制字符串转换为byte[]
	 * 
	 * @param bytes
	 *            byte数组
	 * @return 十六进制进制字符串
	 */
	public static byte[] hexStringToBytes(String hexstr) {
		byte[] b = new byte[hexstr.length() / 2];
		int k = 0;
		for (int i = 0, l = b.length; i < l; i++) {
			char c0 = hexstr.charAt(k++);
			char c1 = hexstr.charAt(k++);
			b[i] = (byte) ((parse(c0) << 4) | parse(c1));
		}
		return b;
	}

	/**
	 * 将字符转换为整数
	 * 
	 * @param c
	 *            需要计算的字符
	 * @return 计算后的整数
	 */
	private static int parse(char c) {
		if (c >= 'a')
			return (c - 'a' + 10) & 0x0f;
		if (c >= 'A')
			return (c - 'A' + 10) & 0x0f;
		return (c - '0') & 0x0f;
	}

	// //////////////////////////////////////////////////////////
	// main测试
	// //////////////////////////////////////////////////////////

	/**
	 * 测试主方法
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws UnsupportedEncodingException {
		String sourceStr = "hello 世界!";
		byte[] encodeBytes = null;
		String encodeStr = null;
		byte[] decodeBytes = null;
		String decodeStr = null;
		String key = null;

		// 原始数据
		System.out.println("原始数据：\t" + sourceStr);
		System.out.println("----------------------------------------");

		/*
		 * BASE64加密解密
		 */
		// BASE64加密
		encodeStr = encryptBASE64(sourceStr.getBytes(ENCODING_UTF8));
		System.out.println("BASE64加密后1：\t" + encodeStr);
		encodeStr = encryptBASE64(sourceStr);
		System.out.println("BASE64加密后2：\t" + encodeStr);
		encodeStr = encryptBASE64(sourceStr, ENCODING_UTF8);
		System.out.println("BASE64加密后3：\t" + encodeStr);
		// BASE64解密
		decodeStr = new String(decryptBASE64(encodeStr), ENCODING_UTF8);
		System.out.println("BASE64解密后1：\t" + decodeStr);
		decodeStr = decryptBASE64ToString(encodeStr);
		System.out.println("BASE64解密后2：\t" + decodeStr);
		decodeStr = decryptBASE64ToString(encodeStr, ENCODING_UTF8);
		System.out.println("BASE64解密后3：\t" + decodeStr);

		System.out.println("----------------------------------------");

		/*
		 * MD5加密
		 */
		encodeStr = bytesToHexString(encryptMD5(sourceStr
				.getBytes(ENCODING_UTF8)));
		System.out.println("MD5加密后1：\t" + encodeStr);
		encodeStr = encryptMD5ToString(sourceStr.getBytes(ENCODING_UTF8));
		System.out.println("MD5加密后2：\t" + encodeStr);
		encodeStr = encryptMD5ToString(sourceStr);
		System.out.println("MD5加密后3：\t" + encodeStr);
		encodeStr = encryptMD5ToString(sourceStr, ENCODING_UTF8);
		System.out.println("MD5加密后4：\t" + encodeStr);

		System.out.println("----------------------------------------");

		/*
		 * SHA加密
		 */
		encodeStr = bytesToHexString(encryptSHA(sourceStr
				.getBytes(ENCODING_UTF8)));
		System.out.println("SHA加密后1：\t" + encodeStr);
		encodeStr = encryptSHAToString(sourceStr.getBytes(ENCODING_UTF8));
		System.out.println("SHA加密后2：\t" + encodeStr);
		encodeStr = encryptSHAToString(sourceStr);
		System.out.println("SHA加密后3：\t" + encodeStr);
		encodeStr = encryptSHAToString(sourceStr, ENCODING_UTF8);
		System.out.println("SHA加密后4：\t" + encodeStr);

		System.out.println("----------------------------------------");

		/*
		 * HMAC带秘钥加密
		 */
		key = bytesToHexString(generatorHMACKey(HMAC_KEY_MAC_MD5));
		System.out.println("HMAC秘钥：\t" + key);

		encodeStr = bytesToHexString(encryptHMAC(
				sourceStr.getBytes(ENCODING_DEFAULT),
				key.getBytes(ENCODING_DEFAULT)));
		System.out.println("HMAC后1：\t" + encodeStr);
		encodeStr = bytesToHexString(encryptHMAC(
				sourceStr.getBytes(ENCODING_DEFAULT),
				key.getBytes(ENCODING_DEFAULT), HMAC_KEY_MAC_MD5));
		System.out.println("HMAC后2：\t" + encodeStr);
		encodeStr = encryptHMACTostring(sourceStr, key);
		System.out.println("HMAC后3：\t" + encodeStr);
		encodeStr = encryptHMACTostring(sourceStr, key, HMAC_KEY_MAC_MD5);
		System.out.println("HMAC后4：\t" + encodeStr);
		encodeStr = encryptHMACTostring(sourceStr, key, HMAC_KEY_MAC_MD5,
				ENCODING_UTF8);
		System.out.println("HMAC后5：\t" + encodeStr);
		System.out.println("----------------------------------------");

		/*
		 * DES带秘钥加密解密
		 */
		key = bytesToHexString(generatorDESKey(hexStringToBytes(sourceStr)));
		System.out.println("DES秘钥：\t\t" + key);

		encodeBytes = encryptDES(sourceStr.getBytes(ENCODING_UTF8),
				hexStringToBytes(key));
		encodeStr = bytesToHexString(encodeBytes);
		System.out.println("DES加密后1：\t" + encodeStr);
		encodeStr = encryptDESToString(sourceStr, key);
		System.out.println("DES加密后2：\t" + encodeStr);
		encodeStr = encryptDESToString(sourceStr, key, ENCODING_UTF8);
		System.out.println("DES加密后3：\t" + encodeStr);

		decodeBytes = decryptDES(hexStringToBytes(encodeStr),
				hexStringToBytes(key));
		decodeStr = new String(decodeBytes, ENCODING_UTF8);
		System.out.println("DES解密后1：\t" + decodeStr);
		decodeStr = decryptDESToString(encodeStr, key);
		System.out.println("DES解密后2：\t" + decodeStr);
		decodeStr = decryptDESToString(encodeStr, key, ENCODING_UTF8);
		System.out.println("DES解密后3：\t" + decodeStr);
		System.out.println("----------------------------------------");

		/*
		 * 3DES带秘钥加密解密
		 */
		key = bytesToHexString(generatorTDESKey(hexStringToBytes(sourceStr)));
		System.out.println("3DES秘钥：\t" + key);

		encodeBytes = encryptTDES(sourceStr.getBytes(ENCODING_UTF8),
				hexStringToBytes(key));
		encodeStr = bytesToHexString(encodeBytes);
		System.out.println("3DES加密后1：\t" + encodeStr);
		encodeStr = encryptTDESToString(sourceStr, key);
		System.out.println("3DES加密后2：\t" + encodeStr);
		encodeStr = encryptTDESToString(sourceStr, key, ENCODING_UTF8);
		System.out.println("3DES加密后3：\t" + encodeStr);

		decodeBytes = decryptTDES(hexStringToBytes(encodeStr),
				hexStringToBytes(key));
		decodeStr = new String(decodeBytes, ENCODING_UTF8);
		System.out.println("3DES解密后1：\t" + decodeStr);
		decodeStr = decryptTDESToString(encodeStr, key);
		System.out.println("3DES解密后2：\t" + decodeStr);
		decodeStr = decryptTDESToString(encodeStr, key, ENCODING_UTF8);
		System.out.println("3DES解密后3：\t" + decodeStr);
		System.out.println("----------------------------------------");

		/*
		 * AES带秘钥加密解密
		 */
		key = bytesToHexString(generatorAESKey(hexStringToBytes(sourceStr)));
		System.out.println("AES秘钥：\t\t" + key);

		encodeBytes = encrypt(sourceStr.getBytes(ENCODING_UTF8),
				hexStringToBytes(key));
		encodeStr = bytesToHexString(encodeBytes);
		System.out.println("AES加密后1：\t" + encodeStr);
		encodeStr = encryptAESToString(sourceStr, key);
		System.out.println("AES加密后2：\t" + encodeStr);
		encodeStr = encryptAESToString(sourceStr, key, ENCODING_UTF8);
		System.out.println("AES加密后3：\t" + encodeStr);

		decodeBytes = decrypt(encodeBytes, Encryption.hexStringToBytes(key));
		decodeStr = new String(decodeBytes, ENCODING_DEFAULT);
		System.out.println("AES解密后1：\t" + decodeStr);
		decodeStr = decryptAESToString(encodeStr, key);
		System.out.println("AES解密后2：\t" + decodeStr);
		decodeStr = decryptAESToString(encodeStr, key, ENCODING_UTF8);
		System.out.println("AES解密后3：\t" + decodeStr);
		System.out.println("----------------------------------------");
	}

}
